using System;
using System.Collections;
using System.Collections.Generic;
using System.Html;
using System.Runtime.CompilerServices;
using System.Serialization;
using Awaiter;
using Nsb;
using Nsb.Classes;
using ThemeChain;
using WhirliGig.Classes;
using Yoshi.Classes;
using jQueryApi;

// ReSharper disable SuspiciousTypeConversion.Global
// ReSharper disable PossibleInvalidCastException

namespace WhirliGigEdit.Classes
{
    [IgnoreNamespace]
    public class Publish : Actor
    {
        private const string PgTop = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\r\n<html xmlns=\"http://www.w3.org/1999/xhtml\">";
        private const string PgEnd = "</html>";

        [PreserveName, PreserveCase]
        public static void PublishThisPageEv(jQueryEvent e)
        {
            CancelEvent(e);
            if (ThemeYoshi.CurrentPageName == ThemeYoshi.AdminPageName)
            {
                GlassOff();
                FlashWindow();
                return;
            }
            Await awx = new Await();
            if (!ThemeYoshi.CurrentPage.Visible)
                awx
                    .AddAw(new Ask().OkCancelAw, new Dictionary("Msg", String.Format("<small>This is a hidden page. If you publish it, then anyone will be able to view it at<br>{0}{1}</small>", ThemeYoshi.BaseUrl(), ThemeYoshi.PublishedUrl())))
                    .AddAw(RequireResultAw, true)
                    ;
            awx
                .AddDx(
                    delegate
                    {
                        Storage.SetLocal(ThemeYoshi.PublishingKey, true);
                        Storage.SetLocal(ThemeBase.CuratingKey, false);
                        ThemeYoshi.PageAction(delegate { PublishThisPage(); });
                        Uri.BumpVersion();
                        ThemeYoshi.ReloadPage();
                    })
                .Commit();
        }

        private static void PublishThisPage()
        {
            new Await()
                .AddAw(PublishThisPageAw)
                .AddDx(
                    delegate
                    {
                        ThemeYoshi.Publishing = false;
                        Storage.RemoveLocal(ThemeYoshi.PublishingKey);
                        Storage.SetLocal(ThemeBase.CuratingKey, true);
                        ThemeYoshi.PageAction(delegate { Ask.Ok("current page is published"); });
                        ThemeYoshi.ReloadPage();
                    })
                .Commit()
                ;
        }

        [PreserveName, PreserveCase]
        public static void PublishEv(jQueryEvent e)
        {
            CancelEvent(e);
            Storage.SetLocal(ThemeYoshi.PublishingKey, true);
            Storage.SetLocal(ThemeBase.CuratingKey, false);
            ThemeYoshi.PageAction(delegate { PublishPage(-1); });
            Uri.BumpVersion();
            ThemeYoshi.ReloadPage();
        }

        [PreserveName, PreserveCase]
        public static void PublishPage(int nxt)
        {
            Inform.Debug("Publishing page idx={0}", nxt);
            int idx = 0;
            Storage.SetSession(ThemeYoshi.PageActionKey, String.Format("Publish.PublishPage({0});", nxt + 1));
            Await awx = new Await();
            foreach (KeyValuePair<string, PageD> pg in ThemeYoshi.Pages.pages)
            {
                if (idx == nxt)
                {
                    if (pg.Value.Visible)
                        awx.AddAw(PublishThisPageAw);
                    else
                        nxt++;
                }
                else if (idx == -1 || idx == nxt + 1)
                {
                    if (pg.Value.Visible)
                    {
                        awx.AddDx(delegate { Script.Literal("Master.GoPage({0}, {1})", ThemeYoshi.CurrentPageClass, pg.Value.Name); });
                        awx.Commit();
                        return;
                    }
                    nxt++;
                }
                idx++;
            }
            awx.AddDx(
                delegate
                {
                    ThemeYoshi.Publishing = false;
                    Storage.RemoveLocal(ThemeYoshi.PublishingKey);
                    ThemeYoshi.PageAction(delegate
                                          {
                                              Storage.SetLocal(ThemeBase.CuratingKey, true);
                                              ThemeYoshi.PageAction(delegate { Ask.Ok("all public pages published"); });
                                              ThemeYoshi.ReloadPage();
                                          });
                    Script.Literal("Master.GoPage({0}, {1})", ThemeYoshi.DefaultPageClass, ThemeYoshi.DefaultPageName);
                });
            awx.Commit();
        }

        [PreserveName, PreserveCase]
        public static void PublishThisPageAw(Await awp)
        {
            Inform.Debug("Publishing current page");
            string pg = "\uFEFF"; // Byte order mark -- seems to be needed to keep unicode characters intact

            jQueryObject links = jQuery.Select("a");

            links.Each(
                delegate(int i, Element domEl)
                {
                    jQueryObject t = jQuery.FromElement(domEl);
                    string href = t.GetAttribute("href");
                    if (href == "javascript:;")
                    {
                        href = Uri.Join("pages", Strings.SafeFileName(t.GetHtml()) + ".html");
                        t.Attribute("href", href);
                    }
                    else if (href.IndexOf(ThemeYoshi.MasterPage) == 0)
                    {
                        href = Uri.Join("pages", (Uri.GetValue(href, "page") ?? ThemeYoshi.DefaultPageName) + ".html");
                        t.Attribute("href", href);
                        t.RemoveAttr("target");
                    }
                }
                );

            // Now get the page content
            string ct = jQuery.Select("html").GetHtml().Trim();

            // Add a <base> tag
            ct = ct.Replace("<head>", "<head>\r\n    <base href=\"" + ThemeYoshi.BaseUrl() + "\">");

            // Embed the version
            ct = ct.ReplaceRegex((RegularExpression) Script.Literal(@"/\d+XvXvXv/"), (Number.ParseInt(Uri.MasterVersion) + 1000) + "XvXvXv");

            // Remove the extra library load
            ct = ct.ReplaceRegex((RegularExpression) Script.Literal(@"/<[s]cript src="".*\/master.js\?_=\d+""><\/[s]cript>/"), "");

            // Remove the extra css load <link rel="Stylesheet" type="text/css" href="master.css?_=' + version + '"/>
            ct = ct.ReplaceRegex((RegularExpression) Script.Literal(@"/<link rel=""Stylesheet"" type=""text\/css"" href=""master.css\?_=.+""\/>/"), "");

            // Cut off the end </body> tag so more can be inserted
            ct = ct.Substr(0, ct.Length - "</body>".Length);

            ct += "\r\n<" + "script type='text/javascript'> jQuery('#PageGigs').hide();<" + "/script>";

            if (ThemeYoshi.CurrentBuildAction != null)
            {
                ct += "\r\n<" + "script type='text/javascript'> setTimeout( function() { try { Build.BuildAction('" + ThemeYoshi.CurrentBuildAction + "'); } catch (ex) {}; }, 1 );<" + "/script>";
            }

            Dictionary tilts = GigShow.GetTilts();

            if (tilts.Count > 0)
            {
                //ct = ct.ReplaceRegex((RegularExpression)Script.Literal(@"/-webkit-transform:[^;]+?;/g"), "");
                ct += "\r\n<" + "script type='text/javascript'> setTimeout( function() { try { Build.Tilt(" + Json.Stringify(tilts) + "); } catch (ex) {} }, 1 );<" + "/script>";
            }

            ct += "\r\n<" + "script type='text/javascript'> setTimeout( function() { try { Build.Finish(); } catch (ex) {} }, 1 );<" + "/script>";

            ct += "\r\n</body>";

            pg += PgTop;
            pg += ct;
            pg += PgEnd;

            //jQuery.Select("base", jQuery.Select("head")).Remove();

            StoreParams pm = new StoreParams();
            pm.partitionKey = "../pages";
            pm.rowKey = ThemeYoshi.CurrentPageName + ".html";
            pm.content = pg;

            Await awx = new Await()
                .AddAw(FileBlobBase.StoreBlobStringAw, (Dictionary) (object) pm)
                ;

            if (ThemeYoshi.CurrentPageName == ThemeYoshi.DefaultPageName)
            {
                // Create the index.html page
                awx
                    .AddDx(
                        delegate
                        {
                            // Remove the <base> tag for the index page.
                            pm.content = pm.content.ReplaceRegex((RegularExpression) Script.Literal(@"/\s*?<base\s+href=[^>]+>/g"), "");
                            pm.partitionKey = "../";
                            pm.rowKey = "index.html";
                        })
                    .AddAw(FileBlobBase.StoreBlobStringAw, (Dictionary) (object) pm)
                    ;
            }
            awx.Commit(awp);
        }
    }
}